import asyncio
from datetime import datetime
from typing import List, Optional

from fastapi import APIRouter, Query, Request

from app.api.deps import CurrentUserDep, LogServiceDep
from app.core import settings
from app.exceptions.base import AppException
from app.schemas.base import Pagination, Response
from app.schemas.log import LogPageVO, VisitStatsVO, VisitTrendVO
from app.utils.date_utils import get_date_range

router = APIRouter(prefix=f"{settings.API_V1_STR}/logs", tags=["08.日志接口"])


@router.get(
    "/page",
    response_model=Response[Pagination[LogPageVO]],
    summary="日志分页列表",
    description="分页查询系统操作日志列表",
)
async def get_log_page(
    current_user: CurrentUserDep,
    log_service: LogServiceDep,
    request: Request,
    page_num: int = Query(1, alias="pageNum", description="页码", ge=1),
    page_size: int = Query(10, alias="pageSize", description="每页记录数", ge=10, le=1000),
    keywords: Optional[str] = Query(
        None, alias="keywords", description="关键字(日志内容/请求路径/请求方法/地区/浏览器/终端系统)"
    ),
    create_time: Optional[List[str]] = Query(None, alias="createTime", description="创建时间(yyyy-MM-dd)"),
) -> Response[Pagination[LogPageVO]]:
    """
    日志分页列表
    """
    # 修复：使用不同的变量名存储提取的时间参数
    extracted_time_params = []
    query_params = dict(request.query_params)
    # 提取createTime[0]和createTime[1]参数
    for key, value in query_params.items():
        if key.startswith("createTime[") and key.endswith("]"):
            extracted_time_params.append(value)

    # 按索引排序
    extracted_time_params.sort(key=lambda x: int(x[0]) if x and x[0].isdigit() else 0)

    # 修复：正确处理空列表和空字符串的情况
    start_date = None
    end_date = None

    if extracted_time_params and len(extracted_time_params) >= 1 and extracted_time_params[0]:
        try:
            start_date = datetime.strptime(extracted_time_params[0], "%Y-%m-%d")
        except ValueError:
            # 日期格式错误处理
            return AppException(message="开始时间格式错误，请使用yyyy-MM-dd格式")

    if extracted_time_params and len(extracted_time_params) >= 2 and extracted_time_params[1]:
        try:
            end_date = datetime.strptime(extracted_time_params[1], "%Y-%m-%d")
        except ValueError:
            # 日期格式错误处理
            return AppException(message="结束时间格式错误，请使用yyyy-MM-dd格式")

    if start_date and end_date:
        if start_date > end_date:
            return AppException(message="开始时间不能大于结束时间")

    rs = await log_service.get_log_page(page_num, page_size, keywords, start_date, end_date)
    return Response(data=rs)


@router.get(
    "/visit-trend",
    response_model=Response[VisitTrendVO],
    summary="获取访问趋势",
    description="查询指定时间范围内的系统访问趋势数据",
)
async def get_visit_trend(
    current_user: CurrentUserDep,
    log_service: LogServiceDep,
    start_date: str = Query(alias="startDate", description="开始时间", example="yyyy-MM-dd"),
    end_date: str = Query(alias="endDate", description="结束时间", example="yyyy-MM-dd"),
) -> Response[VisitTrendVO]:
    """
    获取访问趋势

    Args:
        current_user: 当前登录用户
        log_service: 日志服务实例
        start_date: 开始日期 (yyyy-MM-dd格式)
        end_date: 结束日期 (yyyy-MM-dd格式)

    Returns:
        Response[VisitTrendVO]: 包含日期、IP统计和PV统计的响应对象

    Raises:
        AppException: 当开始时间大于结束时间时抛出异常
    """
    try:
        # 参数验证和转换
        start_date_dt = datetime.strptime(start_date, "%Y-%m-%d")
        end_date_dt = datetime.strptime(end_date, "%Y-%m-%d")

        # 时间范围校验
        if start_date_dt > end_date_dt:
            return AppException(message="开始时间不能大于结束时间")

        # 并行获取统计数据（优化性能）
        _ip_counts, _pv_counts = await asyncio.gather(
            log_service.get_ip_counts(start_date_dt, end_date_dt), log_service.get_pv_counts(start_date_dt, end_date_dt)
        )

        # 生成日期范围
        dates = get_date_range(start_date_dt, end_date_dt)

        # 使用列表推导式优化数据填充（更简洁高效）
        ip_counts = [_ip_counts.get(date, 0) for date in dates]
        pv_counts = [_pv_counts.get(date, 0) for date in dates]

        # 构建响应对象
        visit_trend_data = VisitTrendVO(dates=dates, ip_list=ip_counts, pv_list=pv_counts)

        return Response(data=visit_trend_data)

    except ValueError as e:
        # 日期格式错误处理
        return AppException(message=f"日期格式错误: {str(e)}")
    except Exception as e:
        # 其他异常处理
        return AppException(message=f"获取访问趋势数据失败: {str(e)}")


@router.get(
    "/visit-stats",
    response_model=Response[VisitStatsVO],
    summary="获取访问统计",
    description="获取系统当前的访问统计概览数据",
)
async def get_visit_stats(
    current_user: CurrentUserDep,
    log_service: LogServiceDep,
) -> Response[VisitStatsVO]:
    """
    获取访问统计
    """
    _uv_stats, _pv_stats = await asyncio.gather(log_service.get_uv_stats(), log_service.get_pv_stats())
    visit_stats_vo = VisitStatsVO()
    if _uv_stats:
        visit_stats_vo.today_uv_count = _uv_stats.get("todayCount")
        visit_stats_vo.total_uv_count = _uv_stats.get("totalCount")
        visit_stats_vo.uv_growth_rate = _uv_stats.get("growthRate")
    if _pv_stats:
        visit_stats_vo.today_pv_count = _pv_stats.get("todayCount")
        visit_stats_vo.total_pv_count = _pv_stats.get("totalCount")
        visit_stats_vo.pv_growth_rate = _pv_stats.get("growthRate")
    return Response(data=visit_stats_vo)
